#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->_toolDock = 0;
    this->_projectDock = 0;

    this->_printer = new QPrinter(QPrinter::HighResolution);
    this->ui->graphicsView->setPrinter(this->_printer);

    this->_project = new UmlClassDiagramm();
    this->_project->setMainWindow(this);

    QSettings settings;
    if (settings.contains("savepath")) {
        this->openProject(settings.value("savepath").toString());
    }

    this->initConnections();
}

MainWindow::~MainWindow()
{
    delete this->_project;
    delete this->_toolDock;
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::setProject(UmlProject *project)
{
    this->ui->graphicsView->setScene(project);
}

void MainWindow::paintScene(QPainter *painter, QRectF targetRect, QRectF sourceRect)
{
    QList<QGraphicsItem*> selectedItems = this->_project->selectedItems();

    this->_project->showGuides(false);
    foreach (QGraphicsItem *item, selectedItems) {
        item->setSelected(false);
    }

    this->_project->render(painter, targetRect, sourceRect);

    foreach (QGraphicsItem *item, selectedItems) {
        item->setSelected(true);
    }

    this->_project->showGuides(true);
}

void MainWindow::initConnections()
{    
    // main menu
    QObject::connect(this->ui->actionNewProject, SIGNAL(triggered()), this, SLOT(newProject()));
    QObject::connect(this->ui->actionOpenProject, SIGNAL(triggered()), this, SLOT(openProject()));
    QObject::connect(this->ui->actionSaveProject, SIGNAL(triggered()), this, SLOT(saveProject()));
    QObject::connect(this->ui->actionSaveProjectAs, SIGNAL(triggered()), this, SLOT(saveProjectAs()));
    QObject::connect(this->ui->actionCloseProject, SIGNAL(triggered()), this, SLOT(closeProject()));
    QObject::connect(this->ui->actionCloseProject, SIGNAL(triggered()), this->ui->graphicsView, SLOT(resetScene()));
    QObject::connect(this->ui->actionExit, SIGNAL(triggered()), this, SLOT(quit()));

    // zoom
    QObject::connect(this->ui->actionZoomIn, SIGNAL(triggered()), this->ui->graphicsView, SLOT(zoomIn()));
    QObject::connect(this->ui->actionZoomOut, SIGNAL(triggered()), this->ui->graphicsView, SLOT(zoomOut()));
    QObject::connect(this->ui->actionZoomReset, SIGNAL(triggered()), this->ui->graphicsView, SLOT(zoomReset()));

    // print
    QObject::connect(this->ui->actionPreview, SIGNAL(triggered()), this, SLOT(showPreview()));
    QObject::connect(this->ui->actionPrint, SIGNAL(triggered()), this, SLOT(printfToPage()));
    QObject::connect(this->ui->actionExportTopPDF, SIGNAL(triggered()), this, SLOT(exportToPdf()));
    QObject::connect(this->ui->actionExportToImage, SIGNAL(triggered()), this, SLOT(exportToImage()));

    // import/export
    QObject::connect(this->ui->actionExportXMI_2_1, SIGNAL(triggered()), this, SLOT(exportXMI()));
    QObject::connect(this->ui->actionImportXMI_2_1, SIGNAL(triggered()), this, SLOT(importXMI()));
    QObject::connect(this->ui->actionExportToJava, SIGNAL(triggered()), this, SLOT(exportToJava()));
}

void MainWindow::newProject()
{
    this->saveProject();

    this->closeProject();

    this->_project = new UmlClassDiagramm();
    this->_project->setMainWindow(this);
}

void MainWindow::openProject(QString filePath)
{
    if (!QFile::exists(filePath)) {
        return;
    }

    this->closeProject();

    if (filePath.isEmpty()) {
        filePath = QFileDialog::getOpenFileName(
                this,
                tr("Open WUml-Project"),
                QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation),
                tr("WUml Project (*.wmi)")
            );
    }

    if (QFile::exists(filePath)) {
        IOManager ioManager;
        ioManager.setMainWindow(this);
        ioManager.loadProject(filePath);
        QSettings settings;
        settings.setValue("savepath", filePath);
    }
}

void MainWindow::saveProject()
{
    IOManager ioManager;
    ioManager.saveProject(this->_project);
}

void MainWindow::saveProjectAs()
{
    QString filePath = QFileDialog::getSaveFileName(
                this,
                tr("Save WUml-Project As"),
                QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation),
                tr("WUml Project (*.wmi *.xmi)")
            );


    this->_project->setPath(filePath);
    IOManager ioManager;
    ioManager.setMainWindow(this);
    ioManager.saveProject(this->_project);

    QSettings settings;
    settings.setValue("savepath", filePath);
}

void MainWindow::closeProject()
{
    // deleting project
    if (this->_project) {
        delete this->_project;
        this->_project = 0;
    }

    // hidding and deleting itemDock
    if (this->_toolDock) {
        this->removeDockWidget(this->_toolDock);
        delete this->_toolDock;
        this->_toolDock = 0;
    }

    // hidding and deleting projectDock
    if(this->_projectDock) {
        this->removeDockWidget(this->_projectDock);
        delete this->_projectDock;
        this->_projectDock = 0;
    }
}

void MainWindow::showPreview()
{
    QPrinter printer;

    QPrintPreviewDialog dialog(&printer, this);
    QObject::connect(&dialog, SIGNAL(paintRequested(QPrinter*)), this, SLOT(print(QPrinter*)));
    dialog.exec();
}

void MainWindow::printfToPage()
{
    QPrintDialog dialog(this->_printer);
    if (dialog.exec()) {
        QPainter painter(this->_printer);
        this->paintScene(&painter, QRect(), QRectF());
    }
}

void MainWindow::exportToPdf()
{
    QString path = QFileDialog::getSaveFileName(
            this,
            tr("Exporting as PDF"),
            QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation),
            tr("File (*.pdf)")
            );

    QList<QGraphicsItem*> selectionList = this->_project->selectedItems();

    QRectF sourceRect = selectionList.isEmpty() ? this->_project->sceneRect() : this->_project->selectionRect();

    QSizeF size = sourceRect.size();

    QPrinter pdfPrinter;
    pdfPrinter.setOutputFormat(QPrinter::PdfFormat);
    pdfPrinter.setOutputFileName(path);
    pdfPrinter.setPaperSize(size, QPrinter::Point);
    pdfPrinter.setPageMargins(0, 0, 0, 0, QPrinter::Point);;

    QRectF targetRect = pdfPrinter.paperRect(QPrinter::Point);

    QPainter painter(&pdfPrinter);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    this->paintScene(&painter, targetRect, sourceRect);
    painter.end();
}

void MainWindow::exportToImage()
{
    QList<QGraphicsItem*> selectionList = this->_project->selectedItems();

    QRectF sourceRect = selectionList.isEmpty() ? this->_project->sceneRect() : this->_project->selectionRect();

    QSize size;
    size.setHeight(sourceRect.height());
    size.setWidth(sourceRect.width());

    QImage image(size, QImage::Format_ARGB32);

    QRectF targetRect = image.rect();

    QPainter painter(&image);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.fillRect(image.rect(), Qt::white);
    this->paintScene(&painter, targetRect, sourceRect);
    painter.end();

    QString path = QFileDialog::getSaveFileName(
            this,
            tr("Exporting as Image"),
            QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation),
            tr("File (*.png *.jpg *.gif)")
            );

    image.save(path);
}

void MainWindow::print(QPrinter *printer)
{
    QPainter painter(printer);
    painter.setRenderHint(QPainter::Antialiasing);

    this->_project->clearSelection();
    this->_project->render(&painter);
}

void MainWindow::quit()
{
    qDebug() << "quitting";

    delete this->_project;
    this->_project = 0;

    qApp->quit();
}

void MainWindow::exportToJava()
{
    QString filePath = QFileDialog::getExistingDirectory(
                this,
                tr("Export XMI 2.1"),
                QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation),
                QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
            );

    IOManager ioManager;
    ioManager.exportToJava(this->_project, filePath);
}

void MainWindow::exportXMI()
{
    QString filePath = QFileDialog::getSaveFileName(
                this,
                tr("Export XMI 2.1"),
                QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation),
                tr("XMI Document (*.xmi)")
            );

    IOManager ioManager;
    ioManager.exportXMI(this->_project, filePath);
}

void MainWindow::importXMI()
{
    QString filePath = QFileDialog::getOpenFileName(
                this,
                tr("Import XMI 2.1"),
                QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation),
                tr("XMI Document (*.xmi)")
            );

    if (QFile::exists(filePath)) {
        IOManager ioManager;
        ioManager.setMainWindow(this);
        ioManager.importXMI(filePath);
    }

}
